package pub.gll.plugin.asm.task;

import com.android.build.api.transform.Status;

import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Opcodes;

import java.io.File;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

import pub.gll.plugin.asm.annotation.ArchCollectClassVisitor;
import pub.gll.plugin.asm.annotation.ArchInterfaceCheckVisitor;
import pub.gll.plugin.asm.annotation.AspectClassVisitor;
import pub.gll.plugin.util.ClassUtil;
import pub.gll.plugin.util.FileUtil;
import pub.gll.plugin.util.Log;

/**
 * @author: hujianqiang
 * @date: 2021/4/26
 */

public class CollectJarTask implements Runnable {
    public String TAG="CollectJarTask";
    File fromJar;
    Status status;

    public CollectJarTask(File jarFile, Status status) {
        this.fromJar = jarFile;
        this.status = status;
    }

    @Override
    public void run() {
        ZipFile zipFile = null;
        try {
            zipFile = new ZipFile(fromJar);
            Enumeration<? extends ZipEntry> enumeration = zipFile.entries();
            while (enumeration.hasMoreElements()) {
                ZipEntry zipEntry = enumeration.nextElement();
                String zipEntryName = zipEntry.getName();
                if (ClassUtil.filter(zipEntryName)) {
                    InputStream inputStream = zipFile.getInputStream(zipEntry);
                    ClassReader classReader = new ClassReader(inputStream);
                    ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_MAXS);
                    classReader.accept(createClassVisitorChain(classWriter, status), 0);
                }
            }
        } catch (Exception e) {
            Log.e(TAG, " Jar error : " + e.getMessage());
            e.printStackTrace();
        } finally {
            FileUtil.closeQuietly(zipFile);
        }
    }

    private ClassVisitor createClassVisitorChain(ClassVisitor classVisitor, Status status) {
        ClassVisitor visitor = new AspectClassVisitor(classVisitor);
        ArchInterfaceCheckVisitor checkVisitor = new ArchInterfaceCheckVisitor(Opcodes.ASM7, visitor);
        ClassVisitor archClassVisitor = new ArchCollectClassVisitor(Opcodes.ASM7, checkVisitor, status);
        return archClassVisitor;
    }
}